package com.ciaojian.worker.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ciaojian.core.base.annotation.ApiIdempotent;
import com.ciaojian.core.enums.business.OrderStatusEnum;
import com.ciaojian.core.enums.business.PayTypeEnum;
import com.ciaojian.core.exception.EntityNotFoundException;
import com.ciaojian.core.model.MeituanToken;
import com.ciaojian.core.model.Order;
import com.ciaojian.core.model.vo.OrderSkipVo;
import com.ciaojian.core.util.ApplicationContextHelper;
import com.ciaojian.core.util.LogUtil;
import com.ciaojian.core.util.Result;
import com.ciaojian.worker.meituan.MeituanApi;
import com.ciaojian.worker.meituan.MeituanConfig;
import com.ciaojian.worker.meituan.enums.MeituanStatusCodeEnum;
import com.ciaojian.worker.meituan.kit.MeituanKit;
import com.ciaojian.worker.meituan.mode.Consume;
import com.ciaojian.worker.meituan.response.BaseResponse;
import com.ciaojian.worker.model.param.BadCommentParam;
import com.ciaojian.worker.model.param.ReportMistakenParam;
import com.ciaojian.worker.model.query.WorkerOrderQuery;
import com.ciaojian.worker.service.OrderServiceImpl;
import com.ciaojian.worker.service.StoreServiceImpl;
import com.ciaojian.worker.service.WorkerServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.log4j.Log4j2;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * @author Atlakyn
 */
@Log4j2(topic = "business")
@Api(tags = "订单模块")
@Validated
@RestController
@RequestMapping("/order")
public class OrderController {
    @Resource
    private StoreServiceImpl storeService;
    @Resource
    private OrderServiceImpl orderService;
    @Resource
    private WorkerServiceImpl workerService;

    @ApiOperation("发型师差评订单")
    @GetMapping("/comment/bad")
    public Result getBadComment(@Valid BadCommentParam param) {
        return Result.ok(orderService.getBadComment(param));
    }


    /**
     * @Description: 修改订单为美团订单
     * @Author: xiangchao
     * @Date: 2020/12/7 12:09 下午
     */
    @ApiOperation("修改订单为美团订单")
    @GetMapping("meituanOrder")
    public synchronized Result meituanOrder(@NotNull(message = "订单ID不能为空") @ApiParam(value = "订单Id", required = true) Integer id,
                                            @NotNull(message = "美团金额不能为空") @ApiParam(value = "美团订单金额", required = true) String payTotal,
                                            @NotNull(message = "youzanCode") @ApiParam(value = "劵码", required = true) String youzanCode) {
        Assert.isTrue(!"undefined".equals(youzanCode), "大众点评劵码错误");
        try {
            return workerService.meituanOrder(id, payTotal, youzanCode);
        } catch (Exception e) {
            LogUtil.writeErrorLog(e.toString());
            return Result.error("失败");
        }
    }

    /**
     * 计算订单优惠价格
     *
     * @param orderId          订单 id
     * @param type             服务类型
     * @param code             优惠券码
     * @param memberDiscountId 首单优惠 id
     * @return 计算后的价格
     */
    @ApiOperation("计算订单优惠价格")
    @GetMapping("/cal-amount/{orderId}/{type}")
    public Result calAmount(@PathVariable String orderId,
                            @PathVariable String type,
                            String code,
                            Integer memberDiscountId) {
        // 优惠后的价格
        // 根据 id 查订单
        QueryWrapper<Order> queryOrder = new QueryWrapper<>();
        queryOrder.eq("id", orderId);
        Order order = orderService.getOne(queryOrder);

        BigDecimal amount = orderService.calDiscount(
                order,
                code,
                type,
                memberDiscountId,
                order.getGoodsTotal(),
                order.getUserId());
        return Result.ok(amount);
    }


    @ApiOperation("订单报错")
    @PostMapping("/report-mistaken")
    public Result reportMistaken(@RequestBody @Validated ReportMistakenParam reportMistakenParam) {
        Order order = new Order();
        BeanUtil.copyProperties(reportMistakenParam, order);
        order.updateById();
        return Result.ok();
    }

    @ApiOperation("大众点评核销劵码")
    @PostMapping("/useReceiptCode")
    public Result useReceiptCode(@ApiParam(value = "劵码", required = true) String receiptCode,
                                 @ApiParam(value = "门店名称", required = true) String storeName,
                                 @ApiParam(value = "订单id") Integer orderId) throws Exception {
        Assert.hasText(receiptCode, "劵码不能为空");
        Assert.hasText(storeName, "门店名称不能为空");
        // 获取店面的 微信店铺UUID
        String openShopUuid = storeService.getBaseMapper().getOpenShopUuidByStoreName(storeName.trim());
        Assert.hasText(openShopUuid, "当前门店未配置美团点评商户");
        MeituanToken meituanToken = new MeituanToken().selectById(1);
        // 授权有效期到期,重新授权请求
        if (System.currentTimeMillis() < meituanToken.getExpiresDate()) {
            // 接口授权次数不足,需要到后台进行手动授权
            Assert.isTrue(meituanToken.getRemainRefreshCount() > 0, "美团授权已过期，请提醒商家重新授权");
            MeituanKit.refreshAndGetToken(meituanToken);
        }

        // 获取美团配置
        MeituanConfig meituanConfig = ApplicationContextHelper.getBean(MeituanConfig.class);

        Map<String, Object> params = Consume.builder()
                .app_key(meituanConfig.getAppKey())
                .open_shop_uuid(openShopUuid)
                .requestid(RandomUtil.randomString(32))
                .receipt_code(receiptCode)
                .app_shop_account(meituanConfig.getAppShopAccount())
                .app_shop_accountname(meituanConfig.getAppShopAccountName())
                .count("1")
                .timestamp(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()))
                .v("1")
                .sign_method("MD5")
                .session(meituanToken.getAccessToken())
                .build()
                .createSign(meituanConfig.getSecret());
        // 请求返回结果
        String result = MeituanApi.consume(params);
        ObjectMapper om = new ObjectMapper();
        BaseResponse response = om.readValue(result, BaseResponse.class);
        String dealPrice = null;
        if (CollUtil.isNotEmpty(response.getData())) {
            dealPrice = MapUtil.getStr((Map) response.getData().get(0), "deal_price");
        }

        LogUtil.writeBusinessLog("订单:{%s}券码核销结果:{%s}", orderId, response.getCode());
        if (response.getCode().equals(MeituanStatusCodeEnum.SUCCESS.getCode())) {
            orderService.completeOrderByMeituan(orderId, PayTypeEnum.MEITUAN_PAY);
            return Result.ok(StrUtil.isNotEmpty(dealPrice) ? dealPrice : null);
        }
        return Result.error(response.getCode(), response.getMsg());
    }

    @ApiOperation("修改订单")
    @ApiIdempotent
    @Transactional(rollbackFor = Exception.class)
    @PutMapping("/update/{id}")
    public Result update(@PathVariable Integer id, @RequestBody Order source) {
        Order target = new Order().selectById(id);
        BeanUtil.copyProperties(source, target, CopyOptions.create().setIgnoreNullValue(true));
        target.updateById();
        return Result.ok();
    }

    @ApiOperation("开始服务")
    @PutMapping("/start-service")
    public Result startService(Integer workerId, Integer orderId) {
        Order order = Optional.ofNullable(new Order().selectById(orderId)).orElseThrow(
                () -> new EntityNotFoundException(Order.class, "id", orderId)
        );

        Assert.isTrue(order.getWorkerId().compareTo(workerId) == 0, "不是您的订单");
        Assert.isTrue(order.getStatus().equals(OrderStatusEnum.waiting), "订单不在排队中");

        orderService.startService(order);
        return Result.ok();
    }

    @ApiOperation("完成服务")
    @Transactional(rollbackFor = Exception.class)
    @PutMapping("/{orderId}")
    public Result complete(Integer workerId,
                           @PathVariable Integer orderId) {
        Order order = new Order().selectById(orderId);
        Assert.notNull(order, "请选择订单!");

        Assert.isTrue(order.getWorkerId().compareTo(workerId) == 0, "不是您的订单");
        Assert.isTrue(order.getStatus().equals(OrderStatusEnum.servicing) || order.getStatus().equals(OrderStatusEnum.sling), "订单不在服务中");

        return Result.ok(orderService.complete(order));
    }

    @ApiOperation("取消订单")
    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/cancel/{orderId}")
    public Result cancel(Integer workerId, String reason, @PathVariable Integer orderId) {
        Order order = new Order().selectById(orderId);
        Assert.notNull(order, "请选择订单!");
        Assert.isTrue(order.getWorkerId().compareTo(workerId) == 0, "不是您的订单");
        Assert.isTrue(order.getStatus().equals(OrderStatusEnum.servicing) || order.getStatus().equals(OrderStatusEnum.waiting), "当前不可取消订单");
        Assert.hasLength(reason, "请选择原因");

        order.setStatus(OrderStatusEnum.cancel);
        order.setCancelReason(reason);
        order.updateById();
        return Result.ok();
    }

    @ApiOperation("查询发型师订单")
    @PostMapping("/findWorkerOrder")
    public HashMap<String, Object> findWorkerOrder(@RequestBody WorkerOrderQuery query) {
        return workerService.findWorkerOrder(query);
    }

    @ApiOperation("查询发型师订单")
    @PostMapping("/orderSkip")
    public Result OrderSkipVo(@RequestBody OrderSkipVo orderSkipVo) {
        return workerService.orderSkipVo(orderSkipVo);
    }
}
